#include <iostream>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <cstdlib>
#include <unistd.h>
using namespace std;


template<class T>
class BlockQueue
{
    static const int capacity = 5;
public:
    BlockQueue()
    {
    }
public:
    void Push(T val)
    {
        unique_lock<mutex> lck(_mutex);
        while(q.size() == capacity)
        {
            com_cond.notify_one();
            pro_cond.wait(lck);
        }
        q.push(val);
        if(q.size() == capacity)
        {
            com_cond.notify_one();
        }
    }
    void Pop(T* val)
    {
        unique_lock<mutex> lck(_mutex);
        while(q.size() == 0)
        {
            pro_cond.notify_one();
            com_cond.wait(lck);
        }
        *val = q.front();
        q.pop();
        if(q.size() == 0)
        {
            pro_cond.notify_one();
        }
    }
private:
    mutex _mutex;
    condition_variable pro_cond;
    condition_variable com_cond;
    queue<int> q;
};
void Product(BlockQueue<int>* bq)
{
    while(true)
    {
        int n = rand() % 100;
        bq->Push(n);
        cout << "生产了一个数" << n << endl;
        sleep(1);
    }
}
void Com(BlockQueue<int>* bq)
{
    while(true)
    {
        int n = 0;
        bq->Pop(&n);
        cout << "消费了一个数" << n << endl;
        sleep(1);
    }
}
int main()
{
    srand(time(nullptr));
    BlockQueue<int> bq;
    thread t1(Product, &bq);
    thread t2(Com, &bq);
    t1.join();
    t2.join();
    return 0;
}